package com.puissance4;

import java.util.ArrayList;
import java.util.Random;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.os.Handler;
import android.util.SparseIntArray;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * Classe de gestion de l'activit� PartieUnJoueur.
 * @author Michael
 */
public class PartieUnJoueur extends Activity implements OnClickListener {
	
	// Les jetons de jeu
	private static int _jetonJaune = R.drawable.jeton_jaune;
	private static int _jetonRouge =  R.drawable.jeton_rouge;
	
	// Le handler permettant de mettre � jour l'activit� lorsqu'un sous-thread a termin� son travail
	private Handler _handler = new Handler();
	
	// La liste des jetons
	private static ArrayList<Integer> _listeJeton = null;
	
	// Grille permettant de m�moriser le choix de l'utilisateur
	private static SparseIntArray _grille = null;

	// La couleur du premier jeton pos� (0 = noir, 1 = jaune, 2 = rouge)
	private static int _couleurJeton = 0;
	
	// Cache d'attente utilis� pour avertir l'attente d'une action de la part de l'autre joueur
	private LinearLayout _layoutFinPartie = null;
	
	// Bool�an permettant de savoir si � la fin d'une partie, il y a �galit�
	private Boolean _egalite = false;
	
	// Booléen permettant de savoir si la partie est terminée
	private Boolean _finPartie = false;

	@Override
	public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);
		setContentView(R.layout.partie_un_joueur);
		
		// Initialisation de l'activit�
		this.initialisation();
		
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Pas de menu pour l'instant
		// getMenuInflater().inflate(R.menu.activity_main, menu);
		return true;
	}

	@Override
	public void onBackPressed() {
		
		// On affiche l'activit� nouvelle partie
		Intent intent = new Intent(this.getApplicationContext(), NouvellePartie.class);
		startActivity(intent);
		
		// On termine cette activit�
		finish();
		
	}

	/**
	 * Initialiser l'activit�.
	 */
	public void initialisation() {
		
		// Choisi les bons boutons
		String resBouton = Options.Read(this.getApplicationContext(), "pref_bouton");
		if(resBouton =="")
			resBouton = "0";
		int i = Integer.parseInt(resBouton); 

		switch (i) {
		case 1: 
			_jetonJaune = R.drawable.jeton_jaune; 
			_jetonRouge = R.drawable.jeton_rouge;
		break;
		case 2: 
			_jetonJaune = R.drawable.jeton_jaune2; 
			_jetonRouge = R.drawable.jeton_rouge2;
		break;
		case 3: 
			_jetonJaune = R.drawable.jeton_jaune3; 
			_jetonRouge = R.drawable.jeton_rouge3;
		break;
		case 4: 
			_jetonJaune = R.drawable.jeton_jaune4; 
			_jetonRouge = R.drawable.jeton_rouge4;
		break;
		case 5: 
			_jetonJaune = R.drawable.jeton_jaune5; 
			_jetonRouge = R.drawable.jeton_rouge5;
		break;
		default:
			_jetonJaune = R.drawable.jeton_jaune;
			_jetonRouge = R.drawable.jeton_rouge;
		}
		
		// Bloquer l'orientation de l'activit� en mode portrait
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		
		// Initialiser le jeton du joueur qui commece la partie
		_couleurJeton = 1;
		
		// La liste des jetons
		_listeJeton = new ArrayList<Integer>();

		// Enregisgtrement de tous les jetons dans un tableau
		_listeJeton.add(R.id._imageView1);
		_listeJeton.add(R.id._imageView2);
		_listeJeton.add(R.id._imageView3);
		_listeJeton.add(R.id._imageView4);
		_listeJeton.add(R.id._imageView5);
		_listeJeton.add(R.id._imageView6);
		_listeJeton.add(R.id._imageView7);
		_listeJeton.add(R.id._imageView8);
		_listeJeton.add(R.id._imageView9);
		_listeJeton.add(R.id._imageView10);
		_listeJeton.add(R.id._imageView11);
		_listeJeton.add(R.id._imageView12);
		_listeJeton.add(R.id._imageView13);
		_listeJeton.add(R.id._imageView14);
		_listeJeton.add(R.id._imageView15);
		_listeJeton.add(R.id._imageView16);
		_listeJeton.add(R.id._imageView17);
		_listeJeton.add(R.id._imageView18);
		_listeJeton.add(R.id._imageView19);
		_listeJeton.add(R.id._imageView20);
		_listeJeton.add(R.id._imageView21);
		_listeJeton.add(R.id._imageView22);
		_listeJeton.add(R.id._imageView23);
		_listeJeton.add(R.id._imageView24);
		_listeJeton.add(R.id._imageView25);
		_listeJeton.add(R.id._imageView26);
		_listeJeton.add(R.id._imageView27);
		_listeJeton.add(R.id._imageView28);
		_listeJeton.add(R.id._imageView29);
		_listeJeton.add(R.id._imageView30);
		_listeJeton.add(R.id._imageView31);
		_listeJeton.add(R.id._imageView32);
		_listeJeton.add(R.id._imageView33);
		_listeJeton.add(R.id._imageView34);
		_listeJeton.add(R.id._imageView35);
		_listeJeton.add(R.id._imageView36);
		_listeJeton.add(R.id._imageView37);
		_listeJeton.add(R.id._imageView38);
		_listeJeton.add(R.id._imageView39);
		_listeJeton.add(R.id._imageView40);
		_listeJeton.add(R.id._imageView41);
		_listeJeton.add(R.id._imageView42);

		// Grille permettant de m�moriser le choix de l'utilisateur
		_grille = new SparseIntArray();
		for (Integer item : _listeJeton) {
			_grille.append(item, 0);
		}
		
		// Ajout d'un �couteur sur le click pour chaque jeton
		for (Integer item : _listeJeton) {
			
			final ImageView image = (ImageView) findViewById(item);
			image.setOnClickListener(new OnClickListener() {

				/**
				 * Capter l'�v�nement Click sur la vue.
				 */
				public void onClick(View v) {
					
					// Ouverture d'un sous-thread permettant de mettre � jour l'activit�
					_handler.post(new Runnable() {
				
						/**
						 * Ex�cuter le thread.
						 */
						public void run() {
							
							int indexJeton = _listeJeton.indexOf(image.getId());
							
							// Afficher le jeton choisi par l'utilisateur
							Boolean poserJetonJoueur = afficherJeton(indexJeton);
							
							// Si le jeton a pu �tre pos� (colonne s�lectionn�e non remplie) et que la partie n'est pas terminée
							if (poserJetonJoueur && !_finPartie) {
								
								// Afficher le jeton choisi par l'intelligence artificielle
								int indexJetonAleatoire = genererIndexJetonAleatoire();
								afficherJeton(indexJetonAleatoire);
								
							}
							
						}
						
					});
					
				}
				
			});
			
		}
		
		// Initialiser le cache de fin de partie
		_layoutFinPartie = (LinearLayout) findViewById(R.id._linearLayoutFinPartie);
		
		// Ajouter les �couteurs sur les boutons du cache de fin de partie
		Button boutonFinPartieRejouer = (Button) findViewById(R.id._buttonFinPartieRejouer);
		Button boutonFinPartieQuitter = (Button) findViewById(R.id._buttonFinPartieQuitter);
		boutonFinPartieRejouer.setOnClickListener(this);
		boutonFinPartieQuitter.setOnClickListener(this);
		
		// Ne pas affiche le cache de fin de partie tant que la partie n'est pas termin�e
		_layoutFinPartie.setVisibility(View.GONE);
		
		// Affichage du jeton indiquant qui commence la partie
				ImageView jetonJoueur = (ImageView) findViewById(R.id._imageViewTourJoueur);
				TextView nomJoueur = (TextView) findViewById(R.id._textNomDuJoueur);
				nomJoueur.setText(Options.Read(this.getApplicationContext(), "pref_nom"));
				
				if (_couleurJeton == 1){
					jetonJoueur.setImageResource(_jetonJaune);
					}
				else{
					jetonJoueur.setImageResource(_jetonRouge);
				}
	}
	
	/**
	 * Afficher le jeton dans la case libre la plus basse dans la colonne s�lectionn�e par l'utilisateur.
	 * @param indexCaseSelectionnee
	 * @return
	 */
	public Boolean afficherJeton(int indexCaseSelectionnee) {
	
		Boolean poserJeton = false;
		ImageView caseSelectionnee = (ImageView) findViewById(_listeJeton.get(indexCaseSelectionnee));
			
		// Poser le jeton dans la case la plus basse possible
		int indexImage = _listeJeton.indexOf(caseSelectionnee.getId());
		ImageView caseLibre = null;
		int indexCaseLibre = indexImage;
		int indexColonneCaseLibre = 0;
		
		if (indexImage < 6) {
			
			// 1�re colonne
			int i = 0;
			while (_grille.get(_listeJeton.get(i)) != 0) {
				i++;
				// Si on a atteint le dernier jeton de la grille (en haut � droite)
				if (i == 42)
					break;
			}
			
			if (i < 6) {
				
				// Si la colonne n'est pas enti�rement remplie, r�cup�rer la case libre
				caseLibre = (ImageView)findViewById(_listeJeton.get(i));
				indexCaseLibre = i;
				indexColonneCaseLibre = 1;
				poserJeton = true;
				
			}
			
		}
		else if (indexImage < 12) {
			
			// 2�me colonne
			int i = 6;
			while (_grille.get(_listeJeton.get(i)) != 0) {
				i++;
				// Si on a atteint le dernier jeton de la grille (en haut � droite)
				if (i == 42)
					break;
			}
			
			if (i < 12) {
				
				// Si la colonne n'est pas enti�rement remplie, r�cup�rer la case libre
				caseLibre = (ImageView)findViewById(_listeJeton.get(i));
				indexCaseLibre = i;
				indexColonneCaseLibre = 2;
				poserJeton = true;
				
			}
			
		}
		else if (indexImage < 18) {
			
			// 3�me colonne
			int i = 12;
			while (_grille.get(_listeJeton.get(i)) != 0) {
				i++;
				// Si on a atteint le dernier jeton de la grille (en haut � droite)
				if (i == 42)
					break;
			}
			
			if (i < 18) {
				
				// Si la colonne n'est pas enti�rement remplie, r�cup�rer la case libre
				caseLibre = (ImageView)findViewById(_listeJeton.get(i));
				indexCaseLibre = i;
				indexColonneCaseLibre = 3;
				poserJeton = true;
				
			}
			
		}
		else if (indexImage < 24) {
			
			// 4�me colonne
			int i = 18;
			while (_grille.get(_listeJeton.get(i)) != 0) {
				i++;
				// Si on a atteint le dernier jeton de la grille (en haut � droite)
				if (i == 42)
					break;
			}
			
			if (i < 24) {
				
				// Si la colonne n'est pas enti�rement remplie, r�cup�rer la case libre
				caseLibre = (ImageView)findViewById(_listeJeton.get(i));
				indexCaseLibre = i;
				indexColonneCaseLibre = 4;
				poserJeton = true;
				
			}
			
		}
		else if (indexImage < 30) {
			
			// 5�me colonne
			int i = 24;
			while (_grille.get(_listeJeton.get(i)) != 0) {
				i++;
				// Si on a atteint le dernier jeton de la grille (en haut � droite)
				if (i == 42)
					break;
			}
			
			if (i < 30) {
				
				// Si la colonne n'est pas enti�rement remplie, r�cup�rer la case libre
				caseLibre = (ImageView)findViewById(_listeJeton.get(i));
				indexCaseLibre = i;
				indexColonneCaseLibre = 5;
				poserJeton = true;
				
			}
			
		}
		else if (indexImage < 36) {
			
			// 6�me colonne
			int i = 30;
			while (_grille.get(_listeJeton.get(i)) != 0) {
				i++;
				// Si on a atteint le dernier jeton de la grille (en haut � droite)
				if (i == 42)
					break;
			}
			
			if (i < 36) {
				
				// Si la colonne n'est pas enti�rement remplie, r�cup�rer la case libre
				caseLibre = (ImageView)findViewById(_listeJeton.get(i));
				indexCaseLibre = i;
				indexColonneCaseLibre = 6;
				poserJeton = true;
				
			}
			
		}
		else if (indexImage < 42) {
			
			// 7�me colonne
			int i = 36;
			while (_grille.get(_listeJeton.get(i)) != 0) {
				i++;
				// Si on a atteint le dernier jeton de la grille (en haut � droite)
				if (i == 42)
					break;
			}
			
			if (i < 42) {
				
				// Si la colonne n'est pas enti�rement remplie, r�cup�rer la case libre
				caseLibre = (ImageView)findViewById(_listeJeton.get(i));
				indexCaseLibre = i;
				indexColonneCaseLibre = 7;
				poserJeton = true;
				
			}
			
		}
		
		if (poserJeton) {
			
			// Enregistrer le choix dans la grille
			_grille.delete(caseLibre.getId());
			_grille.append(caseLibre.getId(), _couleurJeton);
		
			// Placer le jeton
			if (_couleurJeton == 1) {
				
				caseLibre.setImageResource(_jetonJaune);
				_couleurJeton = 2;
				
			}
			else if (_couleurJeton == 2) {
				
				caseLibre.setImageResource(_jetonRouge);
				_couleurJeton = 1;
				
			}
			
			// Affichage du jeton indiquant qui � quel joueur c'est le tour de jouer
			ImageView jetonJoueur = (ImageView) findViewById(R.id._imageViewTourJoueur);
			if (_couleurJeton == 1)
				jetonJoueur.setImageResource(_jetonJaune);
			else
				jetonJoueur.setImageResource(_jetonRouge);
			
			// V�rifier si la partie est termin�e
			if (this.verifierEtatPartieTerminee(indexCaseLibre, indexColonneCaseLibre)) {
				
				// Afficher le jeton du joueur ayant gagn� la partie
				TextView textViewTexteGagantFinPartie = (TextView) findViewById(R.id._textViewTexteGagnantFinPartie);
				
				if (_egalite) {
					
					textViewTexteGagantFinPartie.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
					textViewTexteGagantFinPartie.setText(R.string.texte_information_fin_partie_egalite);
					
				} else {
				
					if (_couleurJeton == 1){
						textViewTexteGagantFinPartie.setCompoundDrawablesWithIntrinsicBounds(_jetonRouge, 0, 0, 0);
						Scores.WriteSettings(this.getApplicationContext(), "lose", Scores.ReadSettings(this.getApplicationContext()));
					}
					if (_couleurJeton == 2){
						textViewTexteGagantFinPartie.setCompoundDrawablesWithIntrinsicBounds(_jetonJaune, 0, 0, 0);
						Scores.WriteSettings(this.getApplicationContext(), "win", Scores.ReadSettings(this.getApplicationContext()));
					}
					
					textViewTexteGagantFinPartie.setText(R.string.texte_information_fin_partie_gagnant);
					
				}
				
				// D�sactiver tous les jetons
				for (Integer item : _listeJeton) {
					ImageView image = (ImageView) findViewById(item);
					image.setEnabled(false);
				}
				
				// Afficher le cache de fin de partie
				_layoutFinPartie.setVisibility(View.VISIBLE);
				
			}
			
		}
		
		return poserJeton;
		
	}
	
	/**
	 * Permet de v�rifier si la partie est termin�e.
	 * @param indexImage
	 * @param indexColonne
	 * @return
	 */
	private Boolean verifierEtatPartieTerminee(int indexImage, int indexColonne) {
		
		_finPartie = false;
		Boolean partieTerminee = false;
		int couleur = _grille.get(_listeJeton.get(indexImage));
		int nombreJetonAlignesVertiale = 1;
		int nombreJetonAlignesHorizontal = 1;
		int nombreJetonAlignesDigonaleGaucheDroiteBas = 1;
		int nombreJetonAlignesDiagonaleGaucheDroiteHaut = 1;
		
		// Vertical (haut)
		for (int i = 1; i < 4; i++) {
			int indexJetonATester = indexImage + i; 
			// V�rifier qu'on est dans la grille
			if(indexJetonATester >= 0 && indexJetonATester < 42) {
				// V�rifier qu'on ne change pas de colonne
				if (this.estDansMemeColonne(indexColonne, indexJetonATester)) {
					// V�rifier si la case contient un jeton de la couleur du joueur
					if (_grille.get(_listeJeton.get(indexJetonATester)) == couleur)
						nombreJetonAlignesVertiale++;
					else
						break;
				}
			}
		}
		
		// Vertical (bas)
		for (int i = 1; i < 4; i++) {
			int indexJetonATester = indexImage - i;
			if(indexJetonATester >= 0 && indexJetonATester < 42) {
				if (this.estDansMemeColonne(indexColonne, indexJetonATester)) {
					if (_grille.get(_listeJeton.get(indexJetonATester)) == couleur)
						nombreJetonAlignesVertiale++;
					else
						break;
				}
			}
		}
		
		// Horizontal (droite)
		for (int i = 1; i < 4; i++) {
			int indexJetonATester = indexImage + (i * 6);
			if(indexJetonATester >= 0 && indexJetonATester < 42) {
				if (_grille.get(_listeJeton.get(indexJetonATester)) == couleur)
					nombreJetonAlignesHorizontal++;
				else
					break;
			}
		}
		
		// Horizontal (gauche)
		for (int i = 1; i < 4; i++) {
			int indexJetonATester = indexImage - (i * 6);
			if(indexJetonATester >= 0 && indexJetonATester < 42) {
				if (_grille.get(_listeJeton.get(indexJetonATester)) == couleur)
					nombreJetonAlignesHorizontal++;
				else
					break;
			}
		}
		
		// Diagonale (haut gauche)
		for (int i = 1; i < 4; i++) {
			int indexJetonATester = indexImage - (i * 5);
			// V�rifier qu'on est dans la grille
			if(indexJetonATester >= 0 && indexJetonATester < 42) {
				// V�rifier qu'on change d'une colonne
				if (this.estDansMemeColonne(indexColonne - i, indexJetonATester)) {
					// V�rifier si la case contient un jeton de la couleur du joueur
					if (_grille.get(_listeJeton.get(indexJetonATester)) == couleur)
						nombreJetonAlignesDigonaleGaucheDroiteBas++;
					else
						break;
				}
			}
		}
		
		// Diagonale (bas droite)
		for (int i = 1; i < 4; i++) {
			int indexJetonATester = indexImage + (i * 5);
			if(indexJetonATester >= 0 && indexJetonATester < 42) {
				if (this.estDansMemeColonne(indexColonne + i, indexJetonATester)) {
					if (_grille.get(_listeJeton.get(indexJetonATester)) == couleur)
						nombreJetonAlignesDigonaleGaucheDroiteBas++;
					else
						break;
				}
			}
		}
		
		// Diagonale (haut droite)
		for (int i = 1; i < 4; i++) {
			int indexJetonATester = indexImage + (i * 7);
			if(indexJetonATester >= 0 && indexJetonATester < 42) {
				if (this.estDansMemeColonne(indexColonne + i, indexJetonATester)) {
					if (_grille.get(_listeJeton.get(indexJetonATester)) == couleur)
						nombreJetonAlignesDiagonaleGaucheDroiteHaut++;
					else
						break;
				}
			}
		}
		
		// Diagonale (bas gauche)
		for (int i = 1; i < 4; i++) {
			int indexJetonATester = indexImage - (i * 7);
			if(indexJetonATester >= 0 && indexJetonATester < 42) {
				if (this.estDansMemeColonne(indexColonne - i, indexJetonATester)) {
					if (_grille.get(_listeJeton.get(indexJetonATester)) == couleur)
						nombreJetonAlignesDiagonaleGaucheDroiteHaut++;
					else
						break;
				}
			}
		}
		
		// Sinon v�rifier s'il y a �galit�
		_egalite = true;
		for (int i = 0; i < _grille.size(); i++) {
			if (_grille.valueAt(i) == 0) {
				_egalite = false;
			}
		}
		
		// V�rifier si le joueur qui vient de poser le jeton a gagn�
		if ((nombreJetonAlignesVertiale > 3) || 
				(nombreJetonAlignesHorizontal > 3) || 
				(nombreJetonAlignesDigonaleGaucheDroiteBas > 3) || 
				(nombreJetonAlignesDiagonaleGaucheDroiteHaut > 3)) {
			
			partieTerminee = true;
			// Définir l'état de la partie à terminé
			_finPartie = true;
			
		} else if (_egalite) {
			
			partieTerminee = true;
			// Définir l'état de la partie à terminé
			_finPartie = true;
			
		}
		
		return partieTerminee;
		
	}
	
	/**
	 * Permet de savoir si le jeton se trouve dans la colonne sp�cifi�e.
	 * @param indexColonne
	 * @param indexJeton
	 * @return
	 */
	private Boolean estDansMemeColonne(int indexColonne, int indexJeton) {
		
		Boolean estDansMemeColonne = false;
		
		switch (indexColonne) {
		case 1:
			if (0 <= indexJeton && indexJeton <= 5) {
				estDansMemeColonne = true;
			}
			break;
		case 2:
			if (6 <= indexJeton && indexJeton <= 11) {
				estDansMemeColonne = true;
			}
			break;
		case 3:
			if (12 <= indexJeton && indexJeton <= 17) {
				estDansMemeColonne = true;
			}
			break;
		case 4:
			if (18 <= indexJeton && indexJeton <= 23) {
				estDansMemeColonne = true;
			}
			break;
		case 5:
			if (24 <= indexJeton && indexJeton <= 29) {
				estDansMemeColonne = true;
			}
			break;
		case 6:
			if (30 <= indexJeton && indexJeton <= 35) {
				estDansMemeColonne = true;
			}
			break;
		case 7:
			if (36 <= indexJeton && indexJeton <= 41) {
				estDansMemeColonne = true;
			}
			break;
		default:
			break;
		}
		
		return estDansMemeColonne;
		
	}
	
	/**
	 * G�n�rer un index de jeton al�toire pour la grille de jeu.
	 * @return
	 */
	public int genererIndexJetonAleatoire() {
		
		int indexJetonAleatoire = 0;
		
		Random generateurNombreAleatoire = new Random();
		indexJetonAleatoire = generateurNombreAleatoire.nextInt(42);
		
		// Tester si la case n'a pas d�j� �t� prise
		if (_grille.get(_listeJeton.get(indexJetonAleatoire)) != 0) {
			indexJetonAleatoire = genererIndexJetonAleatoire();
		}
		
		return indexJetonAleatoire;
		
	}
	
	/**
	 * Rejouer une partie.
	 */
	public void rejouerPartie() {
		
		// R�initialiser la grille de jeu
		_grille.clear();
		for (Integer item : _listeJeton) {
			_grille.append(item, 0);
		}
		
		// Activer tous les jetons
		for (Integer item : _listeJeton) {
			ImageView image = (ImageView) findViewById(item);
			image.setEnabled(true);
			image.setImageResource(R.drawable.jeton_noir);
		}
		
		// R�initialiser le jeton du joueur qui commece la partie
		_couleurJeton = 1;
		
		// Affichage du jeton indiquant qui � quel joueur c'est le tour de jouer
		ImageView jetonJoueur = (ImageView) findViewById(R.id._imageViewTourJoueur);
		jetonJoueur.setImageResource(_jetonJaune);
		
		// Enlever le cache de fin de partie
		_layoutFinPartie.setVisibility(View.GONE);
		
	}

	/**
	 * Capter l'�v�nement Click sur la vue.
	 */
	public void onClick(View vue) {
		
		switch (vue.getId()) {
		
		case R.id._buttonFinPartieRejouer:
			// Rejouer une partie
            this.rejouerPartie();
			break;
			
		case R.id._buttonFinPartieQuitter:
			// On affiche l'activit� NouvellePartie
			Intent intentNouvellePartieMultijoueurBluetooth = new Intent(this.getApplicationContext(), NouvellePartie.class);
			startActivity(intentNouvellePartieMultijoueurBluetooth);
			// On termine cette activit�
			finish();
			break;
			
		default:
			break;
			
		}
		
	}
	
}
